package org.celery.modules.statics.controller;

import cn.hutool.core.date.DateTime;
import cn.hutool.core.date.DateUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.github.xiaoymin.knife4j.annotations.ApiOperationSupport;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.AllArgsConstructor;
import org.celery.modules.shop.entity.Shop;
import org.celery.modules.shop.service.IShopService;
import org.celery.modules.statics.service.IDataViewService;
import org.celery.modules.ticket.entity.CustomTicket;
import org.celery.modules.ticket.service.ICustomTicketService;
import org.springblade.core.boot.ctrl.BladeController;
import org.springblade.core.secure.BladeUser;
import org.springblade.core.tool.api.R;
import org.springblade.core.tool.constant.BladeConstant;
import org.springblade.core.tool.utils.Func;
import org.springframework.format.annotation.DateTimeFormat;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.*;
import java.util.stream.Collectors;

@RestController
@AllArgsConstructor
@RequestMapping("statics/data-view")
@Api(value = "数据大屏", tags = "数据大屏接口")
public class DataViewController extends BladeController {

    private final ICustomTicketService customTicketService;
    private final IDataViewService dataViewService;
    private final IShopService shopService;

    /**
     * 最佳店铺
     */
    @GetMapping("/best-shop")
    @ApiOperationSupport(order = 1)
    @ApiOperation(value = "最佳店铺")
    public R<Map<String, Object>> bestShop(@RequestParam(required = false) @DateTimeFormat(pattern="yyyy-MM-dd HH:mm:ss") LocalDateTime startTime,
                                           @RequestParam(required = false) @DateTimeFormat(pattern="yyyy-MM-dd HH:mm:ss") LocalDateTime endTime,
                                           @RequestParam(required = false) String shopName,
                                           BladeUser user) {
        List<Map<String, Object>> list = dataViewService.topList(shopName, startTime, endTime, user);
        if (Func.isEmpty(list)) {
            return R.data(null);
        }
        return R.data(list.get(0));
    }

    /**
     * 概况
     */
    @GetMapping("/overview")
    @ApiOperationSupport(order = 2)
    @ApiOperation(value = "概况")
    public R<Map<String, Object>> overview(@RequestParam(required = false) String shopName, BladeUser user) {
        Map<String, Object> all = subOverView(shopName, null, null, user);
        Map<String, Object> yesterday = subOverView(shopName, DateUtil.beginOfDay(DateUtil.yesterday()), DateUtil.endOfDay(DateUtil.yesterday()), user);
        Map<String, Object> month = subOverView(shopName, DateUtil.beginOfMonth(new Date()), DateUtil.endOfMonth(new Date()), user);

        return R.data(new HashMap<String, Object>() {{
            put("all", all);
            put("yesterday", yesterday);
            put("month", month);
        }});
    }

    private Map<String, Object> subOverView(String shopName, DateTime startTime, DateTime endTime, BladeUser user) {
        QueryWrapper<CustomTicket> queryWrapper = new QueryWrapper<>();
        if (Func.isNotEmpty(startTime) && Func.isNotEmpty(endTime)) {
            queryWrapper.lambda().between(CustomTicket::getDate, startTime, endTime);
        }
        if (Func.isNotEmpty(shopName)) {
            List<Shop> shopList = shopService.list(Wrappers.<Shop>lambdaQuery().like(Shop::getResourceOwner, shopName));
            if (Func.isEmpty(shopList)) {
                return new HashMap<String, Object>() {{
                    put("amount", 0);
                    put("count", 0);
                    put("cost", 0);
                    put("profit", 0);
                }};
            }
            List<Long> shopIdList = shopList.stream().map(Shop::getId).collect(Collectors.toList());
            queryWrapper.lambda().in(CustomTicket::getShopId, shopIdList);
        }
        if(!user.getTenantId().equals(BladeConstant.ADMIN_TENANT_ID) || (!user.getRoleName().contains("administrator") && !user.getRoleName().contains("s_admin") && !user.getRoleName().contains("caiwu") && !user.getRoleName().contains("fake_boss"))) {
            List<Shop> shopList = shopService.authList(user);
            if (Func.isEmpty(shopList)) {
                return new HashMap<String, Object>() {{
                    put("amount", 0);
                    put("count", 0);
                    put("cost", 0);
                    put("profit", 0);
                }};
            }

            List<Long> shopIdList = shopList.stream().map(Shop::getId).collect(Collectors.toList());
            queryWrapper.lambda().in(CustomTicket::getShopId, shopIdList);
        }
        List<CustomTicket> allTicketList = customTicketService.list(queryWrapper);

        BigDecimal totalAmount = new BigDecimal(0);
        BigDecimal totalProfit = new BigDecimal(0);
        BigDecimal totalCost = new BigDecimal(0);
        Integer totalCount = allTicketList.size();

        for (CustomTicket item: allTicketList) {
            totalAmount = totalAmount.add(item.getSalePrice());
            totalProfit = totalProfit.add(item.getProfit());
            totalCost = totalCost.add(item.getPurchasePrice());
        }

        Map<String, Object> data = new HashMap<>();
        data.put("amount", totalAmount);
        data.put("count", totalCount);
        data.put("cost", totalCost);
        data.put("profit", totalProfit);

        return data;
    }

    /**
     * 排行前十
     */
    @GetMapping("/top-ten")
    @ApiOperationSupport(order = 3)
    @ApiOperation(value = "排行前十")
    public R<List<Map<String, Object>>> topTen(@RequestParam(required = false) @DateTimeFormat(pattern="yyyy-MM-dd HH:mm:ss") LocalDateTime startTime,
                                               @RequestParam(required = false) @DateTimeFormat(pattern="yyyy-MM-dd HH:mm:ss") LocalDateTime endTime,
                                               @RequestParam(required = false) String shopName,
                                               BladeUser user) {
        List<Map<String, Object>> list = dataViewService.topList(shopName, startTime, endTime, user);
        if (list.size() <= 10) {
            return R.data(list);
        }
        return R.data(list.subList(0, 9));
    }

    /**
     * 最近十条订单
     */
    @GetMapping("/last-ticket-ten")
    @ApiOperationSupport(order = 4)
    @ApiOperation(value = "最近十条订单")
    public R<List<Map<String, Object>>> lastTicketTen(@RequestParam(required = false) @DateTimeFormat(pattern="yyyy-MM-dd HH:mm:ss") LocalDateTime startTime,
                                                      @RequestParam(required = false) @DateTimeFormat(pattern="yyyy-MM-dd HH:mm:ss") LocalDateTime endTime,
                                                      @RequestParam(required = false) String shopName,
                                                      BladeUser user) {
        List<Map<String, Object>> list = dataViewService.lastTicketList(shopName, startTime, endTime, user);

        if (list.size() < 10) {
            return R.data(list);
        }
        return R.data(list.subList(0, 9));
    }

    /**
     * 最近订单列表
     */
    @GetMapping("/last-ticket-list")
    @ApiOperationSupport(order = 5)
    @ApiOperation(value = "最近订单列表")
    public R<List<Map<String, Object>>> lastTicketList(@RequestParam(required = false) @DateTimeFormat(pattern="yyyy-MM-dd HH:mm:ss") LocalDateTime startTime,
                                                       @RequestParam(required = false) @DateTimeFormat(pattern="yyyy-MM-dd HH:mm:ss") LocalDateTime endTime,
                                                       @RequestParam(required = false) String shopName,
                                                       BladeUser user) {
        return R.data(dataViewService.lastTicketList(shopName, startTime, endTime, user));
    }


}
